/**
 *****************************************************************************
 * DESC ：. 
 * Author : Junwei Zhang 
 * CREATEDATE ：2012-7-4 
 * MODIFYLIST ：       	Name 			 Date 			Reason/Contents
 * 				------------------------------------------------------ 
 * 				 	Junwei Zhang     2012-7-4		Created.
 ****************************************************************************
 **/
package com.me.client;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.jtalker.client.JTalkerParser.OneMember;
import com.me.client.JTalkParser.ClientSettings;
import com.me.client.JTalkParser.OneMessage;

/**
 * 客户端报文解析类. <br/>
 * 上午9:39:38 2012-7-4
 * 
 * @Author <a href="mailto:mestudying@sina.com">Junwei Zhang</a><br/>
 **/
public class JTalkParser extends DefaultHandler {

	private String currentTag = null;
	/** Last received server answer */
	private String lastAnswer = null;
	/** Last received server answer type. */
	private int lastAnswerType = ANSWER_INFO;

	private List<OneMember> listMembers = new ArrayList<OneMember>();
	private List<OneMessage> listMessage = new ArrayList<OneMessage>();
	private Object lastError;
	private boolean parsingConfigFile;
	private ClientSettings clientSettings;

	public static final int ANSWER_INFO = 0;
	private static final int ANSWER_ERROR = 1;
	public static final int ANSWER_UPDATE = 2;

	public static final String MEMBER = "MEMBER";
	public static final String MEMBER_NAME = "name";
	public static final String MEMBER_IP = "ip";
	public static final String MEMBER_STATUS = "status";
	public static final String MEMBER_PASSWD = "passwd";
	public static final String MEMBER_TYPE = "type";
	public static final String MEMBER_SID = "sid";

	public static final String MESSAGE = "MESSAGE";
	public static final String MESSAGE_TYPE = "type";
	public static final String MESSAGE_CONTENT = "content";
	private static final String MESSAGE_SENDER = "sender";
	private static final String MESSAGE_STATUS = "status";
	private static final String MESSAGE_TO = "to";
	private static final String MESSAGE_SUBJECT = "subject";
	private static final String MESSAGE_ID = "id";

	public static final String USER_TYPE_PERSISTENT = "persistent";
	public static final String USER_TYPE_CHATROOM = "chatroom";
	/** Config File Tags */
	public static final String CONFIG_ROOT = "JTALKER-CLIENT";
	public static final String CONFIG_ACCOUNT = "ACCOUNT";
	public static final String CONFIG_ACCOUNT_NAME = "name";
	public static final String CONFIG_ACCOUNT_PASSWD = "passwd";
	public static final String CONFIG_SERVER = "SERVER";
	public static final String CONFIG_SERVER_IP = "ip";
	public static final String CONFIG_SERVER_PORT = "port";
	public static final String CONFIG_SERVER_SSL = "ssl";
	public static final String CONFIG_LOOK = "LOOK";
	public static final String CONFIG_LOOK_PLAF = "plaf";
	public static final String CONFIG_LOOK_TEXTCOLOR = "textcolor";
	public static final String CONFIG_LOOK_BGCOLOR = "bgcolor";
	public static final String CONFIG_APPS = "APPS";
	public static final String CONFIG_APPS_BROWSER = "browser";
	public static final String CONFIG_APPS_MAIL = "mail";
	public static final String CONFIG_NOTIFICATION = "NOTIFICATION";
	public static final String CONFIG_NOTIFICATION_USERLIST = "user_list";
	public static final String CONFIG_PLUGINS = "PLUGINS";
	public static final String CONFIG_PLUGINS_DIR = "plugin_dir";
	public static final String CONFIG_PLUGINS_SHORTCUT = "plugin_shortcuts";

	public boolean parsing(String xmlMessage) {
		// TODO Auto-generated method stub
		this.lastAnswer = null;
		this.lastAnswerType = ANSWER_INFO;
		try {
			// System.err.println("---------xmlMessage---------" + xmlMessage);
			SAXParserFactory parserFactory = SAXParserFactory.newInstance();
			parserFactory.setValidating(false);
			SAXParser parser = parserFactory.newSAXParser();
			InputStream is = new ByteArrayInputStream(xmlMessage.getBytes("UTF-8"));
			parser.parse(is, this);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

		return true;
	}

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		this.currentTag = qName;
		if (this.currentTag.equalsIgnoreCase(MEMBER)) {
			String name = attributes.getValue(MEMBER_NAME);
			String status = attributes.getValue(MEMBER_STATUS);
			String password = attributes.getValue(MEMBER_PASSWD);
			String ip = attributes.getValue(MEMBER_IP);
			String type = attributes.getValue(MEMBER_TYPE);
			String sid = attributes.getValue(MEMBER_SID);
			OneMember oneMember = new OneMember(name, status, password, ip, type, sid);
			this.listMembers.add(oneMember);
		} else if (this.currentTag.equalsIgnoreCase(MESSAGE)) {
			String type = attributes.getValue(MESSAGE_TYPE);
			if ("update".equalsIgnoreCase(type)) {
				this.lastAnswer = attributes.getValue(MESSAGE_CONTENT);
				this.lastAnswerType = ANSWER_UPDATE;
			} else if ("info".equalsIgnoreCase(type)) {
				this.lastAnswer = attributes.getValue(MESSAGE_CONTENT);
				this.lastAnswerType = ANSWER_INFO;
			} else if ("error".equalsIgnoreCase(type)) {
				this.lastAnswer = attributes.getValue(MESSAGE_CONTENT);
				this.lastAnswerType = ANSWER_ERROR;
			} else {
				String content = attributes.getValue(MESSAGE_CONTENT);
				String sender = attributes.getValue(MESSAGE_SENDER);
				String status = attributes.getValue(MESSAGE_STATUS);
				String to = attributes.getValue(MESSAGE_TO);
				String subject = attributes.getValue(MESSAGE_SUBJECT);
				String id = attributes.getValue(MESSAGE_ID);
				OneMessage message = new OneMessage(content, sender, status, to, type, subject, id);
				this.listMessage.add(message);
			}
		} else if (this.currentTag.equalsIgnoreCase(CONFIG_ROOT)) {
			// We are parsing the config file
			this.parsingConfigFile = true;
		} else if (this.currentTag.equalsIgnoreCase(CONFIG_ACCOUNT) && this.parsingConfigFile) {
			this.clientSettings.accountName = attributes.getValue(CONFIG_ACCOUNT_NAME);
			this.clientSettings.accountPasswd = attributes.getValue(CONFIG_ACCOUNT_PASSWD);
		} else if (this.currentTag.equalsIgnoreCase(CONFIG_SERVER) && this.parsingConfigFile) {
			this.clientSettings.serverIP = attributes.getValue(CONFIG_SERVER_IP);
			this.clientSettings.serverPort = attributes.getValue(CONFIG_SERVER_PORT);
			this.clientSettings.serverSSL = attributes.getValue(CONFIG_SERVER_SSL);
		} else if (this.currentTag.equalsIgnoreCase(CONFIG_LOOK) && this.parsingConfigFile) {
			this.clientSettings.lookPlaf = attributes.getValue(CONFIG_LOOK_PLAF);
			this.clientSettings.lookTextcolor = attributes.getValue(CONFIG_LOOK_TEXTCOLOR);
			this.clientSettings.lookBgcolor = attributes.getValue(CONFIG_LOOK_BGCOLOR);
		} else if (this.currentTag.equalsIgnoreCase(CONFIG_APPS) && this.parsingConfigFile) {
			this.clientSettings.appsBrowser = attributes.getValue(CONFIG_APPS_BROWSER);
			this.clientSettings.appsMail = attributes.getValue(CONFIG_APPS_MAIL);
		} else if (this.currentTag.equalsIgnoreCase(CONFIG_NOTIFICATION) && this.parsingConfigFile) {
			this.clientSettings.notifUserlist = attributes.getValue(CONFIG_NOTIFICATION_USERLIST);
		} else if (this.currentTag.equalsIgnoreCase(CONFIG_PLUGINS) && this.parsingConfigFile) {
			this.clientSettings.pluginsDir = attributes.getValue(CONFIG_PLUGINS_DIR);
			this.clientSettings.pluginsShortcuts = attributes.getValue(CONFIG_PLUGINS_SHORTCUT);
		}
	}

	/** Gets the last Server answer (could be an error or an information) */
	public String getAnswer() {
		return this.lastAnswer;
	}

	/** Gets number of members */
	public int getMemberNum() {
		return this.listMembers.size();
	}

	/** Gets a member by number */
	public OneMember getAMember(int index) {
		return this.listMembers.get(index);
	}

	public class OneMember {

		public String name = null;
		public String status = null;
		public String passwd = null;
		public String ip = null;
		public String type = USER_TYPE_PERSISTENT;
		public String sid = null;

		public OneMember(String name, String status, String password, String ip, String type, String sid) {
			this.name = name;
			this.status = status;
			this.ip = ip;
			this.passwd = password;
			this.sid = sid;
			this.type = type == null ? USER_TYPE_PERSISTENT : type;
		}

	}

	/**
	 * 客户端消息类.
	 * 
	 * @author Administrator
	 * 
	 */
	public class OneMessage {

		public String content = null;
		public String sender = null;
		public String senderStatus = null;
		public String messageReceivers = null;
		public String messageType = null;
		public String messageSubject = null;
		public String messageID = null;

		public OneMessage(String content, String sender, String senderStatus, String messageReceivers,
				String messageType, String messageSubject, String id) {
			this.content = content;
			this.sender = sender;
			this.senderStatus = senderStatus;
			this.messageReceivers = messageReceivers;
			this.messageType = messageType;
			this.messageSubject = messageSubject;
			this.messageID = id;
		}
	}

	/**
	 * 客户端设置类.
	 * 
	 * @author Administrator
	 * 
	 */
	public class ClientSettings {

		public String pluginsShortcuts;
		public String pluginsDir;
		public String notifUserlist;
		public String appsMail;
		public String appsBrowser;
		public String lookBgcolor;
		public String lookTextcolor;
		public String lookPlaf;
		public String serverSSL;
		public String serverPort;
		public String serverIP;
		public String accountPasswd;
		public String accountName;

	}

	public int getAnswerType() {
		return this.lastAnswerType;
	}

	/**
	 * 获取消息数量.
	 * 
	 * @return
	 */
	public int getMessageNum() {
		return this.listMessage.size();
	}

	/**
	 * 获取一条消息.
	 * 
	 * @param i
	 * @return
	 */
	public OneMessage getAMessage(int i) {
		return this.listMessage.get(i);
	}

	/**
	 * 解析配置文件.
	 * 
	 * @param myConfig
	 *            配置文件.
	 * @return
	 */
	public boolean parsing(File configFile) {
		this.lastError = null;
		this.parsingConfigFile = false;
		this.clientSettings = new ClientSettings();
		if (!configFile.canRead()) {
			this.lastError = "Can't load file.";
			return false;
		}
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			factory.setValidating(false);
			SAXParser parser = factory.newSAXParser();
			parser.parse(configFile, this);
		} catch (Exception e) {
			return false;
		}
		return this.parsingConfigFile;
	}

	/**
	 * 获取客户端设置对象.
	 * @return
	 */
	public ClientSettings getClientSettings() {
		return this.clientSettings;
	}

}
